import { Prisma, PrismaClient } from '@prisma/client'

interface CliOptions {
  userId?: number
  idNumber?: string
  depositIds: number[]
  apply: boolean
}

interface DepositInfo {
  id: number
  amount: number
  status: string
  createdAt: Date
  processedAt: Date | null
}

const prisma = new PrismaClient()

const formatDecimal = (value: unknown): number => {
  if (value === null || value === undefined) {
    return 0
  }
  if (typeof value === 'number') {
    return value
  }
  if (typeof value === 'bigint') {
    return Number(value)
  }
  if (typeof value === 'object') {
    const decimalLike = value as { toNumber?: () => number }
    if (typeof decimalLike.toNumber === 'function') {
      return decimalLike.toNumber()
    }
  }
  return Number(value)
}

const parseArgs = (): CliOptions => {
  const options: CliOptions = {
    depositIds: [],
    apply: false
  }

  for (const arg of process.argv.slice(2)) {
    if (arg.startsWith('--userId=')) {
      const value = Number(arg.replace('--userId=', '').trim())
      if (Number.isNaN(value)) {
        throw new Error('无效的 --userId 值')
      }
      options.userId = value
    } else if (arg.startsWith('--idNumber=')) {
      const value = arg.replace('--idNumber=', '').trim()
      if (!value) {
        throw new Error('无效的 --idNumber 值')
      }
      options.idNumber = value
    } else if (arg.startsWith('--depositIds=')) {
      const ids = arg
        .replace('--depositIds=', '')
        .split(',')
        .map(item => Number(item.trim()))
        .filter(id => !Number.isNaN(id))
      if (ids.length === 0) {
        throw new Error('请提供至少一个有效的 depositId')
      }
      options.depositIds = ids
    } else if (arg === '--apply') {
      options.apply = true
    } else {
      throw new Error(`未知参数: ${arg}`)
    }
  }

  if (!options.userId && !options.idNumber) {
    throw new Error('请通过 --userId 或 --idNumber 指定目标用户')
  }

  return options
}

const resolveUserId = async (options: CliOptions): Promise<{ userId: number; idNumber: string }> => {
  if (options.userId) {
    const user = await prisma.user.findUnique({
      where: { id: options.userId },
      select: { id: true, idNumber: true }
    })
    if (!user) {
      throw new Error(`未找到ID为 ${options.userId} 的用户`)
    }
    return { userId: user.id, idNumber: user.idNumber }
  }

  const user = await prisma.user.findUnique({
    where: { idNumber: options.idNumber },
    select: { id: true, idNumber: true }
  })

  if (!user) {
    throw new Error(`未找到身份证号为 ${options.idNumber} 的用户`)
  }

  return { userId: user.id, idNumber: user.idNumber }
}

const listConfirmedDeposits = async (userId: number): Promise<DepositInfo[]> => {
  const deposits = await prisma.depositRecord.findMany({
    where: {
      userId,
      status: 'CONFIRMED'
    },
    orderBy: { createdAt: 'asc' },
    select: {
      id: true,
      amount: true,
      status: true,
      createdAt: true,
      processedAt: true
    }
  })

  return deposits.map(item => ({
    id: item.id,
    amount: formatDecimal(item.amount),
    status: item.status,
    createdAt: item.createdAt,
    processedAt: item.processedAt
  }))
}

const ensureBalanceEnough = (current: number, deductions: number): void => {
  if (current - deductions < -0.01) {
    throw new Error(`当前余额不足以扣除 ${deductions.toFixed(2)} KRW，剩余将为 ${(current - deductions).toFixed(2)} KRW`)
  }
}

const removeDeposits = async (userId: number, depositIds: number[], totalAmount: number): Promise<void> => {
  await prisma.$transaction(async (tx: Prisma.TransactionClient) => {
    const balance = await tx.userBalance.findUnique({
      where: { userId },
      select: {
        balance: true,
        total: true
      }
    })

    const currentBalance = balance ? formatDecimal(balance.balance) : 0
    const currentTotal = balance ? formatDecimal(balance.total) : 0

    ensureBalanceEnough(currentBalance, totalAmount)

    await tx.depositRecord.deleteMany({
      where: {
        userId,
        id: { in: depositIds }
      }
    })

    await tx.userBalance.update({
      where: { userId },
      data: {
        balance: new Prisma.Decimal(currentBalance - totalAmount),
        total: new Prisma.Decimal(currentTotal - totalAmount)
      }
    })
  })
}

const main = async (): Promise<void> => {
  const options = parseArgs()
  const { userId, idNumber } = await resolveUserId(options)

  const deposits = await listConfirmedDeposits(userId)

  if (deposits.length === 0) {
    console.log(`用户 ${userId} (${idNumber}) 没有已确认的充值记录。`)
    return
  }

  console.log(`用户 ${userId} (${idNumber}) 的已确认充值记录（按时间顺序）：`)
  for (const deposit of deposits) {
    console.log(
      `  - ID: ${deposit.id}, 金额: ₩${deposit.amount.toFixed(2)}, 创建: ${deposit.createdAt.toISOString()}, 处理: ${deposit.processedAt?.toISOString() ?? '未处理时间'}`
    )
  }

  if (options.depositIds.length === 0) {
    console.log('未指定 --depositIds，未进行任何修改。')
    return
  }

  const targetSet = new Set(options.depositIds)
  const toRemove = deposits.filter(item => targetSet.has(item.id))

  if (toRemove.length === 0) {
    console.log(`指定的充值记录 ${options.depositIds.join(', ')} 未匹配已确认记录，未进行任何修改。`)
    return
  }

  const totalRemoveAmount = toRemove.reduce((sum, item) => sum + item.amount, 0)

  console.log(`\n计划删除的充值记录: ${toRemove.map(item => item.id).join(', ')}`)
  console.log(`总金额: ₩${totalRemoveAmount.toFixed(2)}`)

  if (!options.apply) {
    console.log('\n预览模式（未执行删除操作）。若要生效，请追加 --apply 参数。')
    return
  }

  await removeDeposits(userId, toRemove.map(item => item.id), totalRemoveAmount)

  console.log(`\n已删除充值记录，总金额 ₩${totalRemoveAmount.toFixed(2)}。用户余额已同步扣除。`)
}

main().catch(async error => {
  console.error('删除充值记录失败:', error)
  await prisma.$disconnect()
  process.exit(1)
}).finally(async () => {
  await prisma.$disconnect()
})
